cssshadowsvalue: handle gtk_css_value_transition returning NULL
authorCosimo Cecchi <cosimoc@gnome.org>
Tue, 16 Oct 2012 18:22:24 +0000 (14:22 -0400)
committerCosimo Cecchi <cosimoc@gnome.org>
Tue, 16 Oct 2012 18:22:24 +0000 (14:22 -0400)
The implementation of transition for GtkCssShadowValue can return NULL
at least when the two values have a different inset; all other parts of
the GTK/CSS machinery (e.g. GtkCssArrayValue) handle this by returning
NULL too. Instead, GtkCssShadowsValue was returning an invalid value,
where "len" was set, but some values in the array were NULL, which would
lead to a segfault when this value is later evaluated by the compute
function.

Fix this by making GtkCssShadowsValue return NULL if a shadow transition
fails, like GtkCssArrayValue does.

https://bugzilla.gnome.org/show_bug.cgi?id=686013

gtk/gtkcssshadowsvalue.c

index 267c41c43991b04a8d6bfea8c8493fcfc10be8a1..0438316935a2dfc697ea5abb3826e852146833f4 100644 (file)
@@ -98,42 +98,64 @@ gtk_css_value_shadows_transition (GtkCssValue *start,
                                   guint        property_id,
                                   double       progress)
 {
-  GtkCssValue *result;
-  guint i;
+  guint i, len;
+  GtkCssValue **values;
 
   /* catches the important case of 2 none values */
   if (start == end)
     return _gtk_css_value_ref (start);
 
   if (start->len > end->len)
-    result = gtk_css_shadows_value_new (start->values, start->len);
+    len = start->len;
   else
-    result = gtk_css_shadows_value_new (end->values, end->len);
+    len = end->len;
+
+  values = g_newa (GtkCssValue *, len);
 
   for (i = 0; i < MIN (start->len, end->len); i++)
     {
-      result->values[i] = _gtk_css_value_transition (start->values[i], end->values[i], property_id, progress);
+      values[i] = _gtk_css_value_transition (start->values[i], end->values[i], property_id, progress);
+      if (values[i] == NULL)
+        {
+          while (i--)
+            _gtk_css_value_unref (values[i]);
+          return NULL;
+        }
     }
   if (start->len > end->len)
     {
-      for (; i < result->len; i++)
+      for (; i < len; i++)
         {
           GtkCssValue *fill = _gtk_css_shadow_value_new_for_transition (start->values[i]);
-          result->values[i] = _gtk_css_value_transition (start->values[i], fill, property_id, progress);
+          values[i] = _gtk_css_value_transition (start->values[i], fill, property_id, progress);
           _gtk_css_value_unref (fill);
+
+          if (values[i] == NULL)
+            {
+              while (i--)
+                _gtk_css_value_unref (values[i]);
+              return NULL;
+            }
         }
     }
   else
     {
-      for (; i < result->len; i++)
+      for (; i < len; i++)
         {
           GtkCssValue *fill = _gtk_css_shadow_value_new_for_transition (end->values[i]);
-          result->values[i] = _gtk_css_value_transition (fill, end->values[i], property_id, progress);
+          values[i] = _gtk_css_value_transition (fill, end->values[i], property_id, progress);
           _gtk_css_value_unref (fill);
+
+          if (values[i] == NULL)
+            {
+              while (i--)
+                _gtk_css_value_unref (values[i]);
+              return NULL;
+            }
         }
     }
 
-  return result;
+  return gtk_css_shadows_value_new (values, len);
 }
 
 static void